﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;

using invrt;
using Pibby.Core.Models;
using Pibby.Core.Feeds;
using Pibby.Core.Views;
using Pibby.Core.Web;
using Pibby.Core.IO;

namespace Pibby.Core.Presenters
{
	public class SubscriptionPresenter : Presenter<ISubscriptionListView, IPodcatcherModel>
	{
		private BackgroundProcessing _validationWorker;

		public SubscriptionPresenter(ISubscriptionListView view, IPodcatcherModel model)
			: base(view, model)
		{
		}

		protected override void SubscribeToClientEvents()
		{
			this.View.InitialiseComplete += new EventHandler(View_InitialiseComplete);
			this.View.AddPodcast += new EventHandler<NewPodcastEventArgs>(View_AddPodcast);
			this.View.ExportPodcasts += new EventHandler<FilePersistenceEventArgs>(View_ExportPodcasts);
			this.View.ImportPodcasts += new EventHandler<FilePersistenceEventArgs>(View_ImportPodcasts);
			this.View.RemovePodcast += new EventHandler<RemovePodcastEventArgs>(View_RemovePodcast);
			this.View.RenamePodcast += new EventHandler<RenamePodcastEventArgs>(View_RenamePodcast);
		}

		public override void UnsubscribeToClientEvents()
		{
			this.View.InitialiseComplete -= View_InitialiseComplete;
			this.View.AddPodcast -= View_AddPodcast;
			this.View.ExportPodcasts -= View_ExportPodcasts;
			this.View.ImportPodcasts -= View_ImportPodcasts;
			this.View.RemovePodcast -= View_RemovePodcast;
			this.View.RenamePodcast -= View_RenamePodcast;
		}

        #region Events

		void View_InitialiseComplete(object sender, EventArgs e)
		{
			this.Model.LoadSubscriptions();
			this.View.ShowPodcasts(this.Model.LoadSubscriptions());
		}

		void View_AddPodcast(object sender, NewPodcastEventArgs e)
		{
			var args = new DownloadFilesArgs(new Downloadable()
			{
				Uri = e.Uri,
				InMemoryDownload = true,
				FriendlyName = string.Format("Getting feed from \'{0}\' ", e.Uri.AbsoluteUri),
				Tag = new SubscriptionCookie
				{
					Url = e.Uri.AbsoluteUri,
					SuggestedName = e.Name
				}
			});


			this._validationWorker = BackgroundProcessing.Create<DownloadFilesArgs, ProgressEventArgs>(
												BackgroundMethods.DownloadRssFeeds,
												ValidationBackgroundThread_ProgressChanged,
												ValidationBackgroundThread_RunWorkerCompleted,
												ValidationBackgroundThread_OnException,
												args);

			this._validationWorker.Run();
		}

		private void ValidationBackgroundThread_OnException(Exception ex)
		{
			this._validationWorker.Dispose();
			this._validationWorker = null;
		}

		private void ValidationBackgroundThread_ProgressChanged(ProgressEventArgs args)
		{
			if (args != null && args.Tag != null)
			{
				var tag = args.Tag as SubscriptionCookie;

				if (tag != null)
				{
					try
					{
						this.Model.CreateFeed(new Uri(tag.Url), tag.SuggestedName, tag.Content);
					}
					catch (Feeds.FeedReadException ex)
					{
						this.View.ReportError(tag.Url + " " + ex.Message);
					}
				}
			}
		}

		void ValidationBackgroundThread_RunWorkerCompleted()
		{
			this._validationWorker.Dispose();
			this._validationWorker = null;

			this.View.ShowPodcasts(this.Model.LoadSubscriptions());
		}

		void View_ExportPodcasts(object sender, FilePersistenceEventArgs e)
		{
			var factory = InversionOfController.Factory.CreateTypeOf<ITextWriterFactory>();

			using (var writer = factory.FromFile(e.Path))
			{
				this.Model.ExportSubscriptions(writer);
			}
		}

		void View_ImportPodcasts(object sender, FilePersistenceEventArgs e)
		{
			var factory = InversionOfController.Factory.CreateTypeOf<ITextReaderFactory>();

			using (var reader = factory.FromFile(e.Path))
			{
				this.Model.ImportSubscriptions(reader);
				this.View.ShowPodcasts(this.Model.LoadSubscriptions());
			}
		}

		void View_RemovePodcast(object sender, RemovePodcastEventArgs e)
		{
			var podcast = this.Model.LoadSubscription(e.DbKey);

			this.Model.RemovePodcast(podcast); 
			this.View.ShowPodcasts(this.Model.LoadSubscriptions());
		}

		void View_RenamePodcast(object sender, RenamePodcastEventArgs e)
		{
			var podcasts = this.Model.LoadSubscriptions();

			var podcast = podcasts[e.Guid];

			this.Model.RenamePodcast(podcast, e.NewName);
		}

        #endregion Events
    }
}
